home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Trading on the Edge
/
Trading On The Edge - CD-ROM Toolkit (Wayzata Technology)(2031)(1994).bin
/
mac
/
Mac_Files
/
Software Utilities
/
NN PreProcessing
/
FINBLD.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-08-25
|
28KB
|
883 lines
/* 19:53 12-Aug-92 (finbld.c) Build Financial Data-base */
#include "fin.h"
/************************************************************************
* Copyright(C) 1992 High-Tech Communications. *
* 103 Buckskin Court, Sewickley, PA 15143 *
* *
* Written by Casimir C. Klimasauskas *
* *
* All rights reserved. No part of this program may be reproduced, *
* stored in a retrieval system, or tramsmitted, in any form or by any *
* means, electronic, mechanical, photocopying, recording or otherwise *
* without the prior written permission of the copyright owner, *
* High-Tech Communications. *
* *
* These programs are supplied on an "as-is" basis with no warranties *
* of fitness or operability, either express or implied. *
* *
************************************************************************
*/
/************************************************************************
* *
* FinBld - Generate Merged Financial Data-Base *
* *
************************************************************************
This routine performs the following functions:
- parse a Compu-Serve session
- load an existing data-base [optional]
- merge the Compu-Serve session sections together
- save the merged data-base
The format of the merged data-base is:
\t ticker ticker ticker ...
date open high low ...
... data ...
It uses tab-separated fields so that the file can be easily
read into excel or lotus 1-2-3.
*/
/* --- The following data structures are used for processing ticker file ---
Current Record Data Buffer
Current Record Transformed Data Buffer
Current Record Data Description
Field (Ticker, Field, Data Ptr (CRDB))
Field ...
Input Data-Base Data Buffer
Input Date-Base Description
Field (Ticker, Field, Data Ptr (input DBDB))
Field ...
Output Data-Base Description
Field (Ticker, Field, IDBDB Field Ptr, CRDB Field Ptr)
Field ...
*/
typedef struct _ifield { /* field in a ticker (Current Record/Input DB) */
char *FTickCP; /* ticker symbol */
char *FSymCP; /* field name */
char *FDataCP; /* data pointer */
int FStartI; /* start position */
int FLenI; /* length of field */
} IFIELD;
typedef struct _ofield { /* output data-base field */
char *FTickCP; /* ticker symbol */
char *FSymCP; /* field name */
IFIELD *FCRecTP; /* current record */
IFIELD *FDRecTP; /* data-base record */
} OFIELD;
/************************************************************************
* *
* Data-Base Manipulation Routines *
* *
************************************************************************
DBGetRecI() - read a raw data record from data-base
DBClearInitV() - Clear all data-base fields
DBCheckInitI() - See if dynamic areas are initialized
DBOpenInI() - open data-base & build basic structures
DBReadInI() - read next field into buffer
DBWriteI() - write data-base output
DBCloseI() - close data-base input/output
*/
char *CRRawBufCP = {0}; /* current record raw data buffer */
char *CRBufCP = {0}; /* current record data buffer */
char *DRBufCP = {0}; /* data-base record current record */
char CRDate[10] = {0}; /* current record date */
char DBDate[10] = {0}; /* data-base date */
IFIELD *CRecTF = {0}; /* current record field table */
IFIELD *DRecTF = {0}; /* data base record field table */
OFIELD *ORecTF = {0}; /* output data-base table */
int CRecNI = {0}; /* # of items in CRecTF */
int DRecNI = {0}; /* # of items in DRecTF */
int ORecNI = {0}; /* # of items in ORecTF */
FILE *IDBFP = {0}; /* input data-base file pointer */
FILE *ODBFP = {0}; /* output data-base file pointer */
int IsCREOF = {0}; /* current record "eof" */
int IsDBEOF = {0}; /* data-base record "eof" */
/* --- DBGetRecI() ---
* Read a raw data record from the data-base
*/
int DBGetRecI( bufCP, buflI, idbFP, eofIP ) /* read a data-base record */
char *bufCP; /* input buffer */
int buflI; /* buffer length */
FILE *idbFP; /* input file pointer */
int *eofIP; /* end of file input pointer */
{
register char *sp; /* work string pointer */
if ( idbFP == (FILE *)0 || feof(idbFP) || ferror(idbFP) ||
(eofIP != (int *)0 && *eofIP != 0) )
goto Eof; /* no more to read */
while( (sp = fgets( bufCP, buflI-1, idbFP )) != (char *)0 ) {
while( *sp && *sp <= ' ' ) sp++; /* skip spaces */
if ( *sp != 0 && *sp != '!' ) { /* check for blank line */
for(; *sp; sp++ ) /* kill eol characters */
if ( *sp == '\r' || *sp == '\n' ) break;
*sp = 0;
return( 0 ); /* all is well */
}
}
Eof:
if ( eofIP != (int *)0 ) *eofIP = 1; /* end of file hit */
return( -1 );
}
/* --- DBClearInitV() ---
* Clear all of the structures associated with the data-base
*/
void DBClearInitV() /* clear out data-base structures */
{
unsigned BlkSU; /* size of block to clear */
if ( CRRawBufCP != (char *)0 ) {
BlkSU = 3 * MAXFL + 3;
memset( (void *)CRRawBufCP, 0, BlkSU );
}
if ( CRecTF != (IFIELD *)0 ) {
BlkSU = MAXFIELD * (sizeof(IFIELD)+sizeof(IFIELD)+sizeof(OFIELD));
memset( (void *)CRecTF, 0, BlkSU );
}
IsCREOF = IsDBEOF = 1; /* force EOF on all */
CRecNI = DRecNI = ORecNI = 0; /* clear tables */
return;
}
/* --- DBCheckInitI() ---
* Check to see that all data structures are allocated.
* If not, allocate and initialize them.
*/
int DBCheckInitI() /* check to see data-areas initialized */
{
static int InitedI = {0}; /* flag = 1 if initialized */
unsigned BlkSU; /* block size */
if ( !InitedI ) {
BlkSU = 3 * MAXFL + 3;
if ( (CRRawBufCP = (char *)malloc( BlkSU )) == (char *)0 ) {
fprintf( stderr, "Could not allocate space for data buffers\n" );
exit( 4 );
}
CRBufCP = &CRRawBufCP[ MAXFL + 1 ];
DRBufCP = &CRBufCP[ MAXFL + 1 ];
BlkSU = MAXFIELD*(sizeof(IFIELD)+sizeof(IFIELD)+sizeof(OFIELD));
if ( (CRecTF = (IFIELD *)malloc( BlkSU ) ) == (IFIELD *)0 ) {
fprintf( stderr, "Could not allocate memory for fields\n" );
exit( 5 );
}
DRecTF = &CRecTF[ MAXFIELD ];
ORecTF = (OFIELD *)(&DRecTF[ MAXFIELD ]);
DBClearInitV();
InitedI = 1;
return( 1 );
}
return( 0 );
}
/* --- DBOpenInI() ---
* Open the master data-base file for input.
* Build all of the data structures which describe it.
*/
int DBOpenInI( dbnCP ) /* open up an existing data-base */
char *dbnCP; /* name of data-base to open */
{
char *sp, *ap; /* string pointer */
int lc; /* last character */
int wxI; /* work index */
if ( ! DBCheckInitI() ) /* check memory allocation */
DBClearInitV(); /* clear if already allocated */
if ( IDBFP != (FILE *)0 ) fclose( IDBFP );
if ( (IDBFP = fopen( dbnCP, "r" )) == (FILE *)0 )
return( -1 ); /* could not open file */
/* --- Opened, read in the header information --- */
IsDBEOF = 0;
/* --- parse ticker symbols --- */
if ( DBGetRecI( DRBufCP, MAXFL, IDBFP, &IsDBEOF ) )
goto IOError; /* could not read first line */
for( ap = DRBufCP; *ap != 0; ap = sp+1 ) {
for( sp = ap; *sp && *sp != '\t'; ) sp++;
lc = *sp; *sp = 0;
DRecTF[DRecNI].FTickCP = DCDupCP( ap==sp? "date":DCLwrPkCP( ap ) );
DRecNI++;
if ( lc == 0 || DRecNI >= MAXFIELD ) break;
}
/* --- parse labels associated with tickers --- */
if ( DBGetRecI( DRBufCP, MAXFL, IDBFP, &IsDBEOF ) )
goto IOError; /* could not read second line */
for( wxI= 0, ap = DRBufCP; *ap != 0; ap = sp+1 ) {
for( sp = ap; *sp && *sp != '\t'; ) sp++;
lc = *sp; *sp = 0;
DRecTF[wxI].FSymCP = DCDupCP( ap==sp? "none":DCLwrPkCP( ap ) );
wxI++;
if ( lc == 0 || wxI >= DRecNI ) break;
}
return( 0 ); /* success */
IOError:
fclose( IDBFP );
IDBFP = (FILE *)0;
DBClearInitV();
return( -1 );
}
/* --- DBReadInI() ---
* Read a record from the master data-base, parse the data fields,
* and set up pointers in the header data structures to them.
*/
int DBReadInI() /* read a data-base record */
{
char *sp; /* buffer pointer */
int wxI; /* work index */
long dL; /* date as a long */
/* --- consistency check --- */
if ( IsDBEOF || IDBFP == (FILE *)0 || DRecNI == 0 ||
DRBufCP == (char *)0 )
return( -1 ); /* could not read data-base */
/* --- read next record --- */
if ( DBGetRecI( DRBufCP, MAXFL, IDBFP, &IsDBEOF ) != 0 )
return( -1 );
/* --- record is read, parse it into sub-fields --- */
for( wxI = 0, sp = DRBufCP; wxI < DRecNI; wxI++ ) {
while( *sp && *sp <= ' ' && *sp != '\t' )
sp++; /* skip leading spaces */
if ( *sp != 0 )
DRecTF[wxI].FDataCP = sp; /* point to start of field */
else DRecTF[wxI].FDataCP = "0"; /* fake zero for null fields */
while( *sp && *sp != '\t' )
sp++; /* skip over the data */
if ( *sp != 0 ) *sp++ = 0; /* null terminate it */
}
/* --- fix up the date --- */
dL = Date2BinL( DRecTF[0].FDataCP ); /* get date to long */
strcpy( DBDate, Date2StrCP( dL ) ); /* fix it up */
DRecTF[0].FDataCP = &DBDate[0]; /* point to it */
return( 0 );
}
/* --- DBWriteI() ---
* Write a new record to the master Output data-base.
* Pick where to get data from (session or data-base).
*/
int DBWriteI( ModeI ) /* write to data-base */
int ModeI; /* 0=Header, 1=DB, 2=New Rec; 3=merge */
{
int wxI; /* work index into data */
char *sp; /* string to "write" out */
IFIELD *ifP; /* input field pointer */
OFIELD *ofP; /* output field pointer */
int flgI; /* flag for "pass number" */
static IFIELD NullF = { "", "", "0", 0, 0 };
/* --- sanity check --- */
if ( ModeI < 0 || 3 < ModeI ||
CRRawBufCP == (char *)0 ||
CRecTF == (IFIELD *)0 ||
ORecNI == 0 ||
ODBFP == (FILE *)0 )
return( -1 );
/* --- write out the data fields --- */
flgI = 0;
Next:
for( wxI = 0; wxI < ORecNI; wxI++ ) {
ofP = &ORecTF[wxI];
switch( ModeI ) {
case 0: sp = flgI?ofP->FSymCP:ofP->FTickCP; break; /* header */
case 1: ifP = ofP->FDRecTP; break; /* db record only */
case 2: ifP = ofP->FCRecTP; break; /* new record only */
case 3: ifP = ofP->FCRecTP? ofP->FCRecTP:ofP->FDRecTP; break;
}
if ( ModeI ) sp = ifP? ifP->FDataCP:"0";
if ( wxI ) fputs( "\t", ODBFP ); /* field separator */
fputs( sp, ODBFP ); /* field itself */
}
fputs( "\n", ODBFP ); /* terminal <lf> */
flgI++; /* next pass */
if ( ModeI == 0 && flgI == 1 ) goto Next; /* only on header */
return( 0 ); /* done */
}
/* --- DBCloseI() ---
* Close both the input and output data-base files.
* Reset all of the data structures to prevent any "accidents".
*/
int DBCloseI() /* close data-bases */
{
if ( IDBFP != (FILE *)0 ) { fclose( IDBFP ); IDBFP = (FILE *)0; }
if ( ODBFP != (FILE *)0 ) { fclose( ODBFP ); ODBFP = (FILE *)0; }
DBClearInitV();
return( 0 );
}
/************************************************************************
* *
* Session Parse Routines *
* *
************************************************************************
*/
/* --- Line Types --- */
int LTypeI = {0}; /* current line type */
#define LT_OTHER 0 /* unclassifiable */
#define LT_SESSION 1 /* session level line */
#define LT_TICKER 2 /* ticker in line */
#define LT_FIELDS 3 /* fields & titles */
#define LT_DATA 4 /* line starts with numeric data */
#define LT_EOD 5 /* end of ticker data file */
#define LT_BLANK 6 /* blank line */
#define LT_CONTINUE 7 /* continue type line */
/* NOTE: in a more efficient implementation, these will all be DYNAMIC */
char Ticker[MAXTL+2] = {0}; /* ticker symbol */
char TitleL[MAXSL+2] = {0}; /* title line */
char FieldL[MAXSL+2] = {0}; /* field format line */
char LastL[MAXSL+2] = {0}; /* save last line */
char TempL[MAXSL+2] = {0}; /* Temporary line for data */
int LastIsFieldI = {0}; /* last line is "fields" */
/* --- FindSubstrCP() ---
* Find a sub-string within a longer string.
*/
char *FindSubstrCP( ssp, strp ) /* returns 0 or ptr to end of sstr */
char *ssp; /* sub-string pointer */
char *strp; /* string pointer */
{
int ssfc; /* first char of sub-string */
int ssl; /* sub-string length */
char *csp; /* current string pointer */
ssfc = *ssp; /* get first char */
ssl = strlen( ssp ); /* length of sub-string */
for( csp = strp; (csp = strchr(csp,ssfc)) != (char *)0; csp++ ) {
if ( strncmp( csp, ssp, ssl ) == 0 )
return( &csp[ssl] );
}
return( csp );
}
/* --- TypeLineI() ---
* Figure out what kind of line this is.
* If it is a "ticker line", the ticker symbol is
* space-compressed until it is followed by a \0, or two
* or more spaces.
*/
int TypeLineI( lbp ) /* classify line */
char *lbp; /* line buffer pointer */
{
int c; /* work character */
int bc; /* blank count */
char *sp, *dp; /* source / destination pointer */
char *lnbp; /* last non-blank character */
char *cbp; /* current buffer pointer */
if ( lbp == (char *)0 ) return( LT_EOD );
cbp = lbp; /* work buffer pointer */
while( *cbp && *cbp <= ' ' ) cbp++; /* skip spaces */
if ( *cbp == 0 )
return( LT_BLANK ); /* blank line */
c = *cbp;
if ( '0' <= c && c <= '9' ) return( LT_DATA ); /* data ! */
/* classify by contents */
if ( strncmp( cbp, "-----", 5 ) == 0 )
return( LT_FIELDS );
if ( (sp = FindSubstrCP( "ticker:", cbp )) != (char *)0 ) {
/* ticker symbol, parse out the ticker symbol */
lnbp = (char *)0;
bc = 0;
for( dp = &Ticker[0]; (c = *sp) != '\0'; sp++ ) {
if ( c > ' ' ) {
lnbp = dp;
bc = 0;
} else { bc++; }
if ( lnbp != (char *)0 && bc >= 2 ) break;
if ( c > ' ' ) *dp++ = c;
}
if ( lnbp != (char *)0 ) dp = &lnbp[1];
*dp = '\0';
return( LT_TICKER );
}
if ( (sp = FindSubstrCP( "press <cr> for more", cbp )) != (char *)0 )
return( LT_CONTINUE );
if ( (sp = FindSubstrCP( "commodity:", cbp )) != (char *)0 )
return( LT_SESSION );
if ( (sp = FindSubstrCP( "issue:", cbp )) != (char *)0 )
return( LT_SESSION );
if ( (sp = FindSubstrCP( "last page", cbp )) != (char *)0 )
return( LT_SESSION );
if ( (sp = FindSubstrCP( "compuserve", cbp )) != (char *)0 )
return( LT_SESSION );
return( LT_OTHER );
}
/* --- GetRawSessionLineCP() ---
* Read a line of input data from the session file.
* Convert it to lower case, convert control chars, and
* pad out with trailing spaces.
*/
char *GetRawSessionLineCP( ifp ) /* read next line from input session */
FILE *ifp; /* input file pointer */
{
char *lbp; /* line buffer pointer */
char *rbp; /* return buffer pointer */
char *lnbp; /* last non-blank pointer */
while( (rbp = fgets(TempL,sizeof(TempL),ifp)) != (char *)0 ) {
lnbp = (char *)0;
for( lbp = rbp; *lbp != 0; lbp++ ) {
if ( *lbp <= ' ' ) *lbp = ' ';
else {
if ( 'A' <= *lbp && *lbp <= 'Z' ) *lbp -= 'A'-'a';
lnbp = lbp;
}
}
if ( lnbp != (char *)0 ) {
while( ++lnbp < &TempL[sizeof(TempL)-1] )
*lnbp = ' '; /* pad out with spaces */
*lnbp = 0;
return( rbp );
}
}
return( rbp ); /* EOF or error */
}
/* --- GetSessionLineI() ---
* Reads & classifies session line.
* Saves ticker in Ticker[].
* Saves Titles in TitleL[].
* Saves Fields in FieldL[].
* Works with data in TempL[]. Also uses "LastL[]" to save data.
*/
int GetSessionLineI( ifp ) /* get classified session line */
FILE *ifp; /* input file pointer */
{
FILE *ofp; /* output file pointer */
char *lp; /* line pointer */
int lt; /* line type */
int rc; /* return code */
int lc; /* line count (from ticker) */
static char CurTic[MAXTL+2]={0}; /* work ticker line */
rc = 0; /* good return code */
for(;;) {
lp = GetRawSessionLineCP( ifp ); /* read next line */
switch( TypeLineI( lp ) ) { /* classify the line */
default: /* --- should not happen --- */
case LT_OTHER: /* not classifiable */
memmove( (void *)&LastL[0], (void *)&TempL[0], sizeof(LastL) );
return( LT_OTHER );
case LT_SESSION: /* session line */
SESSION:
CurTic[0] = 0;
return( LT_SESSION );
case LT_TICKER: /* ticker line */
GotTicker:
strcpy( CurTic, Ticker );
return( LT_TICKER );
case LT_FIELDS: /* fields */
memmove( (void *)&FieldL[0], (void *)&TempL[0], sizeof(FieldL) );
memmove( (void *)&TitleL[0], (void *)&LastL[0], sizeof(TitleL) );
return( LT_FIELDS ); /* we got titles & fields */
case LT_DATA: /* valid data line */
return( LT_DATA );
case LT_EOD: /* end of file */
EOD:
LastL[0] = TempL[0] = 0; /* kill work lines */
CurTic[0] = 0; /* kill existing ticker */
return( LT_EOD );
case LT_BLANK: /* blank line */
continue;
case LT_CONTINUE:
/* --- must find: EOD, Data, Session, or Ticker --- */
for(;;) { /* scan for a terminal, skip blanks */
lp = GetRawSessionLineCP( ifp ); /* next input line */
switch( TypeLineI( lp ) ) { /* classify and act */
case LT_EOD: goto EOD;
case LT_DATA: return( LT_DATA );
case LT_SESSION: goto SESSION;
case LT_TICKER:
if ( strcmp( Ticker, CurTic ) != 0 )
goto GotTicker;
}
}
}
}
}
/* --- InputFormatI() ---
* Figure out the input format and build up the appropriate
* data structures.
* NOTE: data-base open initialized all structures.
*/
int InputFormatI()
{
char *sp, *ap; /* work string pointers */
int stI, lnI; /* start offset, length */
int wxI; /* work index */
IFIELD *ifP; /* input field pointer */
DCLwrPkCP( Ticker ); /* scrunch the ticker just in case */
sp = &FieldL[0]; /* field definitions line */
for( wxI = 0; wxI < MAXFIELD; wxI++ ) {
ifP = &CRecTF[CRecNI]; /* current field descriptor */
while( *sp && *sp <= ' ' ) sp++; /* skip leading spaces */
stI = (sp - &FieldL[0]); /* start position */
if ( *sp != '-' && *sp != '=' ) break; /* end of fields */
while( *sp == '-' || *sp == '=' ) sp++; /* parse field itself */
lnI = (sp - &FieldL[0]) - stI; /* length of field */
TitleL[ stI+lnI ] = 0; /* null terminate title */
ifP->FTickCP = DCDupCP( Ticker ); /* ticker */
ifP->FSymCP = DCDupCP(DCLwrPkCP(&TitleL[stI])); /* title */
ifP->FStartI = stI; /* start */
ifP->FLenI = lnI; /* length */
ifP->FDataCP = (char *)0; /* current data */
CRecNI++; /* next field */
}
return( 0 );
}
/* --- OFCmpI() ---
* Compare routine for sorting data-base output fields
*/
int OFCmpI( pa, pb )
void *pa, *pb; /* input pointers */
{
OFIELD *oa, *ob; /* field pointers */
int rc; /* return code */
oa = (OFIELD *)pa;
ob = (OFIELD *)pb;
if ( (rc = strcmp( oa->FTickCP, ob->FTickCP )) == 0 )
rc = strcmp( oa->FSymCP, ob->FSymCP );
return( rc );
}
/* --- OutputFormatI() ---
* Create merged data structures
*/
int OutputFormatI() /* create merged data structures */
{
int dxI; /* data-base input index */
int cxI; /* current input index */
int wxI; /* work index */
IFIELD *ifP; /* input field pointer */
OFIELD *ofP; /* output field pointer */
char *tCP; /* ticker pointer */
char *fCP; /* field name pointer */
/* --- copy to data-base to output description --- */
for( dxI = 0; dxI < DRecNI; dxI++ ) {
ifP = &DRecTF[dxI];
ofP = &ORecTF[ORecNI];
ofP->FTickCP = ifP->FTickCP;
ofP->FSymCP = ifP->FSymCP;
ofP->FDRecTP = ifP;
ofP->FCRecTP = (IFIELD *)0;
ORecNI++;
}
/* --- merge new input record into output description --- */
for( cxI = DRecNI?1:0; cxI < CRecNI; cxI++ ) {
ifP = &CRecTF[cxI];
tCP = ifP->FTickCP;
fCP = ifP->FSymCP;
ofP = &ORecTF[0];
for( wxI = 0; wxI < ORecNI; wxI++, ofP++ ) {
/* --- determine if it is already in output --- */
if ( tCP == ofP->FTickCP && fCP == ofP->FSymCP ) {
ofP->FCRecTP = ifP;
break;
}
}
if ( wxI >= DRecNI ) {
ofP = &ORecTF[ORecNI]; /* append record */
ofP->FTickCP = ifP->FTickCP;
ofP->FSymCP = ifP->FSymCP;
ofP->FDRecTP = (IFIELD *)0;
ofP->FCRecTP = ifP;
ORecNI++; /* record addition */
}
}
ORecTF[0].FTickCP = ""; /* null ticker for date */
ORecTF[0].FCRecTP = &CRecTF[0]; /* date field for merge record */
/* --- Sort data into sequence --- */
qsort( (void *)&ORecTF[1], ORecNI-1, sizeof(OFIELD), OFCmpI );
/* --- all done, return --- */
return( 0 );
}
/* --- ParseSessionLineI() ---
* Parse a line of session data, reformatting it as required
* and updating the input data structures.
*/
int ParseSessionLineI( ) /* parse a session line */
{
IFIELD *ifP; /* input field pointer */
long dL; /* date in "long" format */
char *sp, *dp; /* work string pointers */
char *aCP; /* alternate "clean" buffer */
double rv; /* real value */
int wxI; /* work index */
/* --- set up pointers to each of the data items --- */
for( wxI = 0; wxI < CRecNI; wxI++ ) {
ifP = &CRecTF[wxI]; /* definition of this string */
sp = &TempL[ifP->FStartI]; /* start of string */
sp[ifP->FLenI] = 0; /* end of string */
while( *sp && *sp<=' ' ) sp++; /* remove leading spaces */
ifP->FDataCP = sp; /* point to the string */
for( dp = (char *)0; *sp != 0; sp++ )
if ( *sp > ' ' ) dp = sp;
if ( dp != (char *)0 ) dp[1] = 0; /* truncate trailing spaces */
}
/* --- make the date into consistent format --- */
dL = Date2BinL( CRecTF[0].FDataCP );
strcpy( CRDate, Date2StrCP( dL ) );
CRecTF[0].FDataCP = CRDate; /* update formated date */
/* --- fix up all of the numeric fields in the record --- */
aCP = &CRBufCP[0]; /* current record "work" buffer */
for( wxI = 1; wxI < CRecNI; wxI++ ) {
ifP = &CRecTF[wxI]; /* definition of this string */
if ( *(ifP->FDataCP) == 0 ) ifP->FDataCP = "0";
else {
rv = Asc2NumD( ifP->FDataCP, ifP->FLenI );
sprintf( aCP, "%.4f", rv ); /* new number */
for( dp = &aCP[strlen(aCP)-1]; dp > aCP; dp-- ) {
if ( *dp == '0' ) { *dp = 0; continue; }
if ( *dp == '.' ) *dp = 0;
break;
}
ifP->FDataCP = aCP;
aCP += strlen( aCP ) + 1;
}
}
return( 0 );
}
/* --- ProcessSessionI() ---
* Process an input session merging the data into the master
* data-base.
*/
int ProcessSessionI( sesfnCP, dbfnCP ) /* Process Session file */
char *sesfnCP; /* name of session file to open */
char *dbfnCP; /* data-base file name */
{
FILE *sFP=(FILE *)0; /* session file pointer */
int stateI; /* state of processing */
int typeI; /* type of line from input session */
int flagI; /* flag for where we are (state) */
long CRCDateL; /* current record date */
long CDBDateL; /* current data-base date */
static char TempFN[] = {"temp.db"}; /* work file */
memset( (void *)&Ticker[0], 0, sizeof(Ticker) );
memset( (void *)&TitleL[0], 0, sizeof(TitleL) );
memset( (void *)&FieldL[0], 0, sizeof(FieldL) );
memset( (void *)&LastL[0], 0, sizeof(LastL) );
memset( (void *)&TempL[0], 0, sizeof(TempL) );
if ( (sFP = fopen( sesfnCP, "r" )) == (FILE *)0 ) {
fprintf( stderr, "Could not open session file <%s>\n", sesfnCP );
return( -1 );
}
stateI = 0; /* initial state */
for(;;) { /* search for ticker */
while( stateI != 2 ) {
switch( GetSessionLineI( sFP ) ) {
default:
case LT_OTHER: break;
case LT_SESSION: stateI = 0; break;
case LT_TICKER: stateI = 1; break;
case LT_FIELDS: stateI = stateI==1?2:0; break;
case LT_DATA: stateI = 0; break;
case LT_EOD: goto EOD;
}
}
/* --- Ticker, Titles & Fields are all valid --- */
/* --- Open Master Data-Base for input & output --- */
fprintf( stderr, "Processing ticker <%s> in file <%s>\n",
Ticker, sesfnCP );
if ( DBOpenInI( dbfnCP ) != 0 ) {
fprintf( stderr, "Could not open input data-base <%s>\n", dbfnCP );
fprintf( stderr, "Creating new data-base\n" );
}
if ( (ODBFP = fopen( TempFN, "w" )) == (FILE *)0 ) {
fprintf( stderr, "Could not open temp data-base <%s>\n", TempFN );
break;
}
/* --- Build input data Structures --- */
InputFormatI();
/* --- Create merged data Structures --- */
OutputFormatI();
DBWriteI( 0 ); /* write out header */
/* --- Read first record of data-base --- */
DBReadInI();
CDBDateL = IsDBEOF? 0L:Date2BinL( DRecTF[0].FDataCP );
for( stateI = 0; stateI == 0;) {
switch( (typeI = GetSessionLineI( sFP )) ) {
case LT_EOD:
case LT_SESSION:
case LT_TICKER: stateI = 1; continue;
case LT_FIELDS:
case LT_OTHER: continue;
case LT_DATA:
ParseSessionLineI(); /* parse the data */
CRCDateL = Date2BinL( CRecTF[0].FDataCP );
while( IsDBEOF == 0 && CRCDateL > CDBDateL ) {
DBWriteI( 1 ); /* write data-base record */
DBReadInI();
CDBDateL = IsDBEOF? 0L:Date2BinL( DRecTF[0].FDataCP );
}
if ( IsDBEOF || CRCDateL < CDBDateL ) {
DBWriteI( 2 ); /* write input record */
} else if ( CRCDateL == CDBDateL ) {
DBWriteI( 3 ); /* write merged record */
DBReadInI(); /* read next db record */
CDBDateL = IsDBEOF? 0L:Date2BinL( DRecTF[0].FDataCP );
}
}
}
while( !IsDBEOF ) {
DBWriteI( 1 ); /* write data-base record */
DBReadInI(); /* read next record */
}
if ( ferror( ODBFP ) ) {
fprintf( stderr, "Errors closing temp data-base. Not Updated.\n" );
flagI = 1;
} else flagI = 0;
DBCloseI(); /* close data-bases */
if ( flagI == 0 ) {
unlink( dbfnCP ); /* kill old file */
rename( TempFN, dbfnCP ); /* replace with new */
}
/* --- Determine how to proceed forward --- */
if ( typeI == LT_EOD ) break; /* exit on EOF */
stateI = typeI == LT_TICKER?1:0; /* set current state */
}
EOD:
if ( sFP != (FILE *)0 ) fclose( sFP );
DBClearInitV();
return( 0 );
}
/* --- main() ---
* Main Driver program for data-base manager
*
* Command line format:
* finbld dbase session session session ...
*/
main( ac, av )
int ac; /* # of arguments */
char *av[]; /* list of arguments */
{
int wI; /* work index */
if ( ac < 3 ) {
fprintf( stderr, "USE: FINBLD data_base session [session..]\n" );
exit( 1 );
}
for( wI = 2; wI < ac; wI++ )
ProcessSessionI( av[wI], av[1] );
exit( 0 );
}